package org.ala.tree.lsm.sstable.block;

import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeMap;

import org.ala.tree.lsm.tools.KryoTools;

/**
 * 索引块
 * <p>	[[key长度:key偏移量:key], [key长度:key偏移量:key], ..., [key长度:key偏移量:key]]
 * <p>	key长度：4字节
 * <p>	key偏移量（key所在的DataBlock在数据区地址）：4字节
 * <p>	索引快总长记录在TAIL区
 *
 * @author ala
 * @date 2025年5月28日
 */
public class IndexBlock<V> {
	/**
	 * 	条目头长度
	 */
	public static final int ITEM_HEAD_LEN = 8;
	
	
	/**
	 * 	条目数
	 */
	protected int count = 0;
	/**
	 * 	记录key和其偏移量
	 */
	protected List<Integer> poses;
	protected List<String> keys;
	
	public IndexBlock() {
		poses = new LinkedList<>();
		keys = new LinkedList<>();
	}
	
	/**
	 * 	追加DataBlock
	 */
	public void append(int pos, DataBlock<V> db) {
		count++;
		poses.addLast(pos);
		keys.addLast(db.key);
	}
	
	
	/**
	 * 	编码
	 */
	public ByteBuffer encode() {
		//	序列化key
		byte[][] ks = new byte[count][];
		int p = 0, c = 0;
		while (!keys.isEmpty()) {
			byte[] bytes = KryoTools.serializ(keys.getFirst());
			ks[p++] = bytes;
			keys.removeFirst();
			c += bytes.length;
		}
		c += count * 8;
		
		ByteBuffer buf = ByteBuffer.allocateDirect(c);
		for (int i = 0 ; i < ks.length ; i++) {
			buf.putInt(ks[i].length);
			buf.putInt(poses.removeFirst());
			buf.put(ks[i]);
		}
		buf.flip();
		return buf;
	}
	/**
	 * 	解码
	 */
	public static <V> IndexBlock<V> decode(ByteBuffer buf) {
		IndexBlock<V> ib = new IndexBlock<>();
		while (buf.remaining() > ITEM_HEAD_LEN) {
			int keyLen = buf.getInt(), 
				keyOffset = buf.getInt();
			if (buf.remaining() < keyLen) {break;}
			
			byte[] bytes = new byte[keyLen];
			buf.get(bytes);
			String key = KryoTools.deSerialize(bytes, String.class);
			
			ib.keys.add(key);
			ib.poses.add(keyOffset);
			ib.count++;
		}
		return ib;
	}
	
	
	/**
	 * 	构建key与下标红黑树
	 */
	public TreeMap<String, Integer> keyOffsetIndex() {
		TreeMap<String, Integer> tree = new TreeMap<>();
		for (int i = 0 ; i < count ; i++) {
			tree.put(keys.get(i), poses.get(i));
		}
		return tree;
	}
	
}
